package com.ceair.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ceair.entity.SysDictData;
import com.ceair.entity.request.dictionary.DictDataInOrUpReq;
import com.ceair.entity.request.dictionary.QueryDictDataReq;
import com.ceair.entity.result.PageResult;
import com.ceair.entity.result.Result;
import com.ceair.entity.vo.dictionary.SysDictDataVO;
import com.ceair.service.ISysDictDataService;
import com.ceair.utils.SysDictDataStructMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @author wangbaohai
 * @ClassName SysDictDataController
 * @description: 字典数据控制器
 * @date 2025年03月28日
 * @version: 1.0.0
 */
@RestController
@RequestMapping("/api/v1/dictData")
@RequiredArgsConstructor
@Slf4j
@Tag(name = "字典数据", description = "字典数据相关接口")
public class SysDictDataController {

    private final ISysDictDataService sysDictDataService;

    /**
     * 分页查询字典数据信息。
     *
     * @param queryDictDataReq 查询字典数据请求参数，包含分页和过滤条件等信息，不能为空。
     *                         该参数通过请求体传递，需符合 {@link QueryDictDataReq} 的结构定义。
     * @return 包含字典数据信息的分页结果，返回类型为 {@link PageResult<List<SysDictDataVO>>}。
     *         其中，列表中的每个元素为字典数据的视图对象（VO），分页结果还包含总记录数。
     *
     * 功能描述：
     * 1. 调用服务层方法进行分页查询，获取字典数据的分页结果。
     * 2. 将查询结果中的实体对象转换为视图对象（VO），并过滤掉转换失败的记录。
     * 3. 返回包含转换后视图对象列表和总记录数的分页结果。
     */
    @PreAuthorize("hasAnyAuthority('/api/v1/dictData/page')")
    @Parameter(name = "queryDictDataReq", description = "查询字典数据请求参数", required = true)
    @Operation(summary = "分页查询字典数据信息")
    @PostMapping("/page")
    public PageResult<List<SysDictDataVO>> queryDictDataWithPage(@RequestBody QueryDictDataReq queryDictDataReq) {
        // 调用服务层方法进行分页查询，获取字典数据信息的分页数据
        Page<SysDictData> page = sysDictDataService.queryDictDataWithPage(queryDictDataReq);

        // 将查询结果中的记录转换为视图对象（VO）列表，并过滤掉转换失败的记录
        List<SysDictDataVO> list =
                Optional.ofNullable(page.getRecords()).orElse(Collections.emptyList()).parallelStream().map(record -> {
                    try {
                        // 使用映射器将实体对象转换为视图对象
                        return SysDictDataStructMapper.INSTANCE.toVO(record);
                    } catch (Exception e) {
                        // 记录转换失败的错误信息
                        log.error("转换数据字典明细信息失败 具体原因为 : {}", e.getMessage());
                        return null;
                    }
                }).filter(Objects::nonNull).toList();

        // 将不可变集合转换为可变集合
        List<SysDictDataVO> mutableList = new ArrayList<>(list);

        // 根据 sortOrder 字段对 mutableList 进行排序，明确处理 null 值的优先级是最后的
        mutableList.sort(Comparator.comparing(SysDictDataVO::getSortOrder, Comparator.nullsLast(Integer::compareTo)));

        // 返回包含转换后列表和列表大小的分页结果
        return PageResult.success(mutableList, page.getTotal());
    }

    /**
     * 保存字典数据信息。
     *
     * <p>该方法通过调用服务层的保存逻辑，将传入的字典数据请求对象保存到系统中，并返回操作结果。</p>
     *
     * @param dictDataInOrUpReq 字典数据信息保存请求对象，包含需要保存或更新的字典数据信息，不能为空。
     *                           该参数通过HTTP请求体传递，需符合 {@link DictDataInOrUpReq} 的定义。
     * @return {@link Result<SysDictDataVO>} 返回一个封装了操作结果的对象：
     *         - 如果保存成功，返回包含 {@link SysDictDataVO} 数据的成功结果；
     *         - 如果保存失败，返回包含错误信息的失败结果。
     *
     * <p>权限要求：调用者需具备 "/api/v1/dictData/save" 的权限。</p>
     */
    @PreAuthorize("hasAnyAuthority('/api/v1/dictData/save')")
    @Parameter(name = "dictDataInOrUpReq", description = "字典数据信息保存请求对象", required = true)
    @Operation(summary = "保存字典数据信息")
    @PostMapping("/save")
    public Result<SysDictDataVO> save(@RequestBody DictDataInOrUpReq dictDataInOrUpReq) {
        // 初始化字典数据视图对象
        SysDictDataVO sysDictDataVO;

        // 调用服务层方法保存字典数据信息，并捕获可能的异常
        try {
            sysDictDataVO = sysDictDataService.save(dictDataInOrUpReq);
        } catch (Exception e) {
            // 记录异常日志并返回错误响应
            log.error("新增或更新字典数据失败 具体原因为 : {}", e.getMessage());
            return Result.error("新增或更新字典数据失败,失败原因：" + e.getMessage());
        }

        // 返回保存成功的响应结果
        return Result.success(sysDictDataVO);
    }

}
